package dao

import (
	"file-download-server/vo"
	"fmt"
	"sort"
	"sync"
)

// FileTaskDAO 负责管理文件任务，保证并发安全
type FileTaskDAO struct {
	tasks  map[int64]*vo.FileTaskRequest // 存放所有任务
	mutex  sync.RWMutex                  // 控制 tasks map 的并发访问
	nextID int64                         // 自增任务 ID
}

// GetLock 获取指定任务的独立锁
func (dao *FileTaskDAO) GetLock(taskID int64) *sync.Mutex {
	return getTaskLock(taskID)
}

// 每个任务独立的锁
var taskLocks sync.Map

// 全局实例
var FileTaskDB = &FileTaskDAO{
	tasks:  make(map[int64]*vo.FileTaskRequest),
	nextID: 1,
}

// getTaskLock 获取指定任务的独立锁
func getTaskLock(taskID int64) *sync.Mutex {
	val, _ := taskLocks.LoadOrStore(taskID, &sync.Mutex{})
	return val.(*sync.Mutex)
}

// CreateTask 创建任务（带独立锁）
func (dao *FileTaskDAO) CreateTask(task *vo.FileTaskRequest) int64 {
	dao.mutex.Lock()
	defer dao.mutex.Unlock()

	task.TaskID = dao.nextID
	dao.tasks[dao.nextID] = task
	taskLocks.Store(dao.nextID, &sync.Mutex{}) // 注册独立锁
	dao.nextID++
	return task.TaskID
}

// UpdateTask 更新任务状态与信息（任务级锁）
func (dao *FileTaskDAO) UpdateTask(taskID int64, status, msg string) {
	lock := getTaskLock(taskID)
	lock.Lock()
	defer lock.Unlock()

	dao.mutex.RLock()
	task, ok := dao.tasks[taskID]
	dao.mutex.RUnlock()

	if ok {
		task.Status = status
		task.Message = msg
	}
}

// UpdateUploadedChunks 更新已上传分片数（任务级锁）
func (dao *FileTaskDAO) UpdateUploadedChunks(taskID int64, uploaded int) {
	lock := getTaskLock(taskID)
	lock.Lock()
	defer lock.Unlock()

	dao.mutex.RLock()
	task, ok := dao.tasks[taskID]
	dao.mutex.RUnlock()

	if ok {
		task.UploadedChunks = uploaded
	}
}

// UpdateDownloadedChunks 更新已下载分片数（任务级锁）
func (dao *FileTaskDAO) UpdateDownloadedChunks(taskID int64, downloaded int) {
	lock := getTaskLock(taskID)
	lock.Lock()
	defer lock.Unlock()

	dao.mutex.RLock()
	task, ok := dao.tasks[taskID]
	dao.mutex.RUnlock()

	if ok {
		task.DownloadedChunks = downloaded
	}
}

// DeleteTask 删除任务（任务级锁 + 全局锁）
func (dao *FileTaskDAO) DeleteTask(fileName string) {
	dao.mutex.Lock()
	defer dao.mutex.Unlock()

	for id, task := range dao.tasks {
		if task.FileName == fileName {
			delete(dao.tasks, id)
			taskLocks.Delete(id) // 删除对应任务锁
		}
	}
}

// DeleteTaskByID 删除指定任务ID
func (dao *FileTaskDAO) DeleteTaskByID(taskID int64) {
	dao.mutex.Lock()
	defer dao.mutex.Unlock()

	delete(dao.tasks, taskID)
	taskLocks.Delete(taskID)
}

// ListTasks 返回所有任务
func (dao *FileTaskDAO) ListTasks() []*vo.FileTaskRequest {
	dao.mutex.RLock()
	defer dao.mutex.RUnlock()

	result := make([]*vo.FileTaskRequest, 0, len(dao.tasks))
	for _, task := range dao.tasks {
		result = append(result, task)
	}
	// 按 TaskID 升序排列
	sort.Slice(result, func(i, j int) bool {
		return result[i].TaskID < result[j].TaskID
	})
	return result
}

// GetTask 根据任务ID获取任务详情
func (dao *FileTaskDAO) GetTask(taskID int64) (*vo.FileTaskRequest, error) {
	dao.mutex.RLock()
	defer dao.mutex.RUnlock()

	task, ok := dao.tasks[taskID]
	if !ok {
		return nil, fmt.Errorf("任务ID %d 不存在", taskID)
	}
	return task, nil
}

// UpdateStatus 更新任务状态
func (db *FileTaskDAO) UpdateStatus(taskID int64, status string) {
	db.mutex.Lock()
	defer db.mutex.Unlock()
	if t, ok := db.tasks[taskID]; ok {
		t.Status = status
	}
}
